package com.polaris.live.ui.main.fragment

import android.os.Bundle
import androidx.annotation.CallSuper
import androidx.lifecycle.MutableLiveData
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import com.polaris.live.adapter.home.HomeManAdapter
import com.polaris.live.common.adapter.BaseAdapter
import com.polaris.live.common.cacha.CacheUtil
import com.polaris.live.common.mvvm.viewmodel.BaseViewModel
import com.polaris.live.common.network.state.ResultState
import com.polaris.live.manager.UserStateManager
import com.polaris.live.resp.back_resp.DisplayUserBean
import com.polaris.live.resp.back_resp.copyState
import com.polaris.live.resp.base.ListResp
import com.polaris.live.utils.block.BlockEventMessage
import com.polaris.live.utils.interfaces.OnAutoRefreshListener
import com.polaris.live.utils.state.getDisplayPosition
import com.polaris.live.widget.refresh.OnListListener
import com.polaris.live.widget.refresh.RefreshRecyclerView
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

/**
 * 热门主页基类
 *
 * @author Created by lucas on 2023/10/17 15:45
 * @since 1.0.0
 */
abstract class AbstractHotListFragment<VM, VB> : AbstractBannerPromptFragment<VM, VB>(),
    OnAutoRefreshListener where VB : ViewBinding, VM : BaseViewModel, VM : OnListListener {

    private var lastRefreshTime: Long? = null

    @CallSuper
    override fun initView(savedInstanceState: Bundle?) {
        super.initView(savedInstanceState)

        mAdapter.setGridSpanSizeLookup { gridLayoutManager, viewType, _ ->
            if (viewType == HomeManAdapter.TYPE_NORMAL) {
                1
            } else {
                gridLayoutManager.spanCount
            }
        }
        refreshView.apply {
            recycler.layoutManager = layoutManager
            attachedAdapter(mAdapter, mViewModel).observeFilter(
                this@AbstractHotListFragment,
                listLiveData,
                { src, dest ->
                    val srcId = if (src is DisplayUserBean) {
                        src.base.userId
                    } else {
                        Long.MAX_VALUE / 2 + src.hashCode()
                    }
                    val destId = if (dest is DisplayUserBean) {
                        dest.base.userId
                    } else {
                        Long.MAX_VALUE / 2 + dest.hashCode()
                    }

                    srcId.compareTo(destId)
                }) {
                if (this == 0) {
                    lastRefreshTime = CacheUtil.getServerTime()
                }
            }
        }

        UserStateManager.observe(this, {
            getDisplayUserIds()
        }, { messages ->
            val indices = refreshView.recycler.getDisplayPosition(mAdapter.data)?.indices
                ?: mAdapter.data.indices

            messages.forEach { message ->
                for (i in indices) {
                    val item = mAdapter.getItem(i)
                    if (item is DisplayUserBean && item.base.userId == message.state.userId) {
                        mAdapter.setData(i, item.copyState(message))
                        break
                    }
                }
            }
        })

        initListener()
    }

    override fun initData() {
        super.initData()
        requireView().post { refreshView.autoRefresh() }
    }

    override fun onAutoRefresh() {
        if (!isCreated() || !isLoadData()) {
            return
        }

        refreshView.recycler.scrollToPosition(0)
        refreshView.autoRefresh()
    }

    abstract fun initListener()

    abstract val refreshView: RefreshRecyclerView

    abstract val layoutManager: RecyclerView.LayoutManager

    abstract val mAdapter: BaseAdapter<Any, *>

    abstract val listLiveData: MutableLiveData<ResultState<ListResp<Any>>>

    override fun onResume() {
        toRefresh()

        super.onResume()
    }

    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)

        if (!hidden) {
            toRefresh()
        }
    }

    private fun toRefresh() {
        if (isLoadData()) {
            val lastRefreshTime = lastRefreshTime
            if (lastRefreshTime == null || CacheUtil.getServerTime() - lastRefreshTime > 60 * 1000) {
                onAutoRefresh()
            }
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onVersionUpdateEvent(event: BlockEventMessage) {
        clearBlacklistedUsers(event)
    }

    private fun clearBlacklistedUsers(event: BlockEventMessage) {
        val iterator = mAdapter.data.iterator()
        while (iterator.hasNext()) {
            val item = iterator.next()
            if (item is DisplayUserBean) {
                if (item.base.userId == event.userId) {
                    iterator.remove()
                }
            }
        }
        mAdapter.notifyDataSetChanged()
    }

    private fun getDisplayUserIds(): List<Long> {
        val wrapper = refreshView.recycler.getDisplayPosition(mAdapter.data)
            ?: return emptyList()

        return mAdapter.data.subList(wrapper.firstPosition, wrapper.lastPosition).mapNotNull {
            if (it is DisplayUserBean) {
                it.base.userId
            } else {
                null
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        EventBus.getDefault().unregister(this)
    }
}